const { app, BrowserWindow, MessageChannelMain } = require('electron')
const path = require('path')
const getIPCConst = import('../src/consts/ipc.js')

function getCreateWindowInstance(maxCount) {
  let windows = [] // 缓存窗口实例
  let max = maxCount || 10 // 创建窗口的最大数量

  // 用于第一个子进程与其它子进程之间的通信，暂存用（从第二个每次创建子进程窗口，都会生成一个MessageChannelMain，port1传给子进程）
  let portPlaceholder = null

  const createWindow = (url) => {
    if (windows.length >= max) return
    try {
      const window = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          preload: path.join(__dirname, 'preload.js'),
          nodeIntegration: false, // 禁用 Node 集成，推荐使用 preload 脚本
          contextIsolation: true, // 保护上下文隔离
        },
      })
      window.loadURL(url)

      // 第一个创建的窗口，打开调试控制台
      // if (windows.length === 0) {
      //   window.webContents.openDevTools()
      // }
      window.webContents.openDevTools()

      // 如果该窗口关闭，则从windows变量中删除
      window.on('closed', () => {
        console.log('窗口已关闭')
        const mainWindow = windows[0]
        const index = windows.findIndex((win) => win === window)
        if (index !== -1) {
          windows.splice(index, 1)
        }
        // 如果第一个窗口关闭，则关闭和清空所有窗口，并应用推出
        if (window === mainWindow) {
          windows.forEach((window) => {
            window.close()
          })
          windows = []
          app.quit()
        }
      })

      windows.push(window)
      return window
    } catch (e) {
      console.log('窗口创建失败:', e)
    }
    return null
  }

  // 创建一个MessageChannelMain，并且让主进程与某个子进程建立通信，将node或electron API暴露给子进程的应用中
  const createMessageChannelAndPostMainToChild = ({ window, type, onMessage, initMsg }) => {
    const { port1, port2 } = new MessageChannelMain()
    // 测试日志用
    port2.postMessage(initMsg)
    port2.on('message', onMessage)
    port2.start()
    window.webContents.postMessage(type, null, [port1])
  }

  // 创建一个MessageChannelMain，并且让第一个子进程与某个子进程建立通信
  const createMessageChannelAndPostChildToChild = ({ window, type, onMessage, initMsg }) => {
    const mainWindow = windows[0]
    const { port1, port2 } = new MessageChannelMain()
    // 测试日志用
    port2.postMessage(initMsg)
    port2.on('message', onMessage)
    port2.start()
    window.webContents.postMessage(type, { isFirst: false }, [port1])
    mainWindow.webContents.postMessage(type, { isFirst: true }, [port2])
  }

  const bindMessagePort = async (window) => {
    if (!window) return
    const mainWindow = windows[0]
    const { CREATE_WINDOW, MAIN_WORLD_PORT, CHILD_TO_CHILD_WORLD_PORT } = await getIPCConst
    createMessageChannelAndPostMainToChild({
      window,
      type: MAIN_WORLD_PORT,
      onMessage: (event) => {
        console.log('from renderer main world:', event.data)
        const { type, url } = event.data

        if (type === CREATE_WINDOW) {
          const win = createWindow(url)
          bindMessagePort(win)
        }
      },
      initMsg: '我是主进程消息~（为了主与子进程通信）',
    })

    if (window !== mainWindow) {
      // 如果当前窗口是后来新建的窗口，而不是第一次创建的子进程渲染窗口，则需要将第一次子进程窗口与该子进程窗口建立通信，以便满足主页面可以和其它子页面相互通信的需求
      createMessageChannelAndPostChildToChild({
        window,
        type: CHILD_TO_CHILD_WORLD_PORT,
        onMessage: (event) => {
          console.log('from renderer main world 2:', event.data)
        },
        initMsg: '我是主进程消息~（为了子与子进程通信）',
      })
    }
  }

  return {
    windows,
    createWindow,
    bindMessagePort,
  }
}

module.exports = {
  getCreateWindowInstance,
}
